perm filename PAUX1.2[EAL,HE] blob sn#676455 filedate 1982-09-27 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	{$NOMAIN	Parser auxilliary routines }
C00004 00003	(* lookup functions: upperCase, eqStrng, hash, resLookup, idLookup, enterIdent *)
C00009 00004	(* aux routines: makeNewVar, makeUVar & varLookup *)
C00014 00005	(* aux routine: appendEnd *)
C00017 00006	(* aux routines for parsing expressions: defNode, getDtype, checkarg, copyExpr *)
C00023 00007	(* basic read routine: readLine *)
C00029 ENDMK
C⊗;
{$NOMAIN	Parser auxilliary routines }

%include palhdr.pas;

{ Externally defined routines from elsewhere: }

	(* From ALLOC *)
function newNode: nodep;					external;
procedure relNode(n: nodep);					external;
procedure relIdent(n: identp);					external;
procedure relStrng(n: strngp);					external;
function newVaridef: varidefp;					external;
function newStatement: statementp;				external;

	(* Display-related Routines *)
procedure ppLine; 						external;
procedure ppOutNow; 						external;
procedure ppChar(ch: ascii); 					external;
procedure pp5(ch: c5str; length: integer); 			external;
procedure pp10(ch: cstring; length: integer); 			external;
procedure pp10L(ch: cstring; length: integer);			external;
procedure pp20(ch: c20str; length: integer); 			external;
procedure pp20L(ch: c20str; length: integer); 			external;
procedure ppInt(i: integer); 					external;
procedure ppStrng(length: integer; s: strngp); 			external;
procedure ppDtype(d: datatypes);				external;

	(* From CALLER *)
function p1eReadLine(var line: linestr): integer;		external;

procedure pAux1Get; external;
procedure pAux1Get; begin end;
(* lookup functions: upperCase, eqStrng, hash, resLookup, idLookup, enterIdent *)

function upperCase(c: ascii): ascii; external;
function upperCase;
 begin
 if (c < chr(141B)) or (chr(172B) < c) then upperCase := c
  else upperCase := chr(ord(c) - 40B);		(* c - 'a' + 'A' *)
 end;

function eqStrng(s1: strngp; s2,len: integer): boolean; external;
function eqStrng;
 var i,j: integer; b: boolean; c1,c2: ascii;
 begin
 b := true;
 i := 0;
 j := 1;
 repeat
  c1 := upperCase(s1↑.ch[j]);
  c2 := upperCase(line[s2+i]);
  if c1 <> c2 then b := false
   else
    begin
    i := i + 1;
    if j < 10 then j := j + 1
     else begin j := 1; s1 := s1↑.next end;
    end
 until (i >= len) or not b;
 eqStrng := b;
 end;

function hash(ch: ascii): integer; external;
function hash;
 var i: integer;
 begin			(* this will only work for ascii *)
 i := ord(ch);
 if ('A' <= ch) and (ch <= 'Z') then i := i - ord('A') + 1
  else if (chr(141B) <= ch) and (ch <= chr(172B)) then i := i - 141B + 1
  else i := 0;
 hash := i;
 end;

function resLookup(str,len: integer): reswordp; external;
function resLookup;
 var res: reswordp; b: boolean;
 begin
 res := reswords[hash(line[str])];	(* look in right bucket *)
 b := true;
 while (res <> nil) and b do
  if res↑.length = len then
    if eqStrng(res↑.name,str,len) then b := false
     else res := res↑.next
   else res := res↑.next;
 resLookup := res;
 end;

function idLookup(str,len: integer): identp; external;
function idLookup;
 var id: identp; b: boolean;
 begin
 id := idents[hash(line[str])];		(* look in right bucket *)
 b := true;
 while (id <> nil) and b do
  if id↑.length = len then
    if eqStrng(id↑.name,str,len) then b := false
     else id := id↑.next
   else id := id↑.next;
 idLookup := id;
 end;

function getReswords(ch: ascii): reswordp; external;
function getReswords;
 begin
 getReswords := reswords[hash(ch)];	(* pass back right bucket *)
 end;

function getIdents(ch: ascii): identp; external;
function getIdents;
 begin
 getIdents := idents[hash(ch)];		(* pass back right bucket *)
 end;

(* aux routines: makeNewVar, makeUVar & varLookup *)

function makeNewVar(vartype: datatypes; vid: identp): varidefp; external;
function makeNewVar;
 var v: varidefp;
 begin
 v := newVaridef;
 with v↑ do
  begin
  vtype := vartype;
  dtype := nil;
  name := vid;
  next := nil;
  tbits := 0;
  dnext := nil;
  dbits := 0;
  s := nil;
  if curBlock <> nil then level := curBlock↑.level else level := 0;
  if curVariable <> nil then
    begin
    offset := curVariable↑.offset + 1;
    curVariable↑.next := v;	(* add var to current block's list of vars *)
    end
   else
    begin
    offset := 0;
    if curBlock <> nil then curBlock↑.variables := v;
    end;
  end;
 curVariable := v;
 makeNewVar := v;
 end;

function makeUVar(vartype: datatypes; vid: identp): varidefp; external;
function makeUVar;
 var v,oldCurVariable: varidefp; sp,oldCurBlock: statementp;
 begin
 oldCurVariable := curVariable;
 oldCurBlock := curBlock;
 curBlock := outerBlock;		(* assume outermost block *)
 v := curProc;			(* unless in body of an enclosing procedure *)
 while v <> nil do
  begin
  sp := oldCurBlock;
  while sp <> nil do
   if v↑.p↑.level + 1 = sp↑.level then
     begin curBlock := sp; v := nil; sp := nil end
    else if v↑.p↑.level >= sp↑.level then sp := nil else sp := sp↑.bparent;
  if v <> nil then v := v↑.dnext;
  end;
 curVariable := curBlock↑.variables;
 if curVariable <> nil then		(* find last defined variable *)
  while curVariable↑.next <> nil do curVariable := curVariable↑.next;
 v := makeNewVar(vartype,vid);
 sp := newStatement;	(* add a new declaration statement to start of block *)
 with sp↑ do
  begin
  stype := declaretype; variables := v; numvars := 1;
  last := curBlock; next := curBlock↑.bcode;
  end;
 if newDeclarations = nil then newDeclarations := sp;	(* for edit *)
 with curBlock↑ do 
  begin                                        (* splice us into block *)
  if bcode <> nil then bcode↑.last := sp;
  bcode := sp;
  end;
 curBlock := oldCurBlock;
 curVariable := oldCurVariable;
 makeUVar := v;
 end;

function varLookup(id: identp): varidefp; external;
function varLookup;
 var v,vp: varidefp; st: statementp; b,bp: boolean;
 begin
 st := curBlock;
 vp := curProc;
 bp := vp <> nil;
 b := true;
 while (st <> nil) and b do
  begin
  if bp then
    if vp↑.level = st↑.level then
      begin			(* check procedures parameter's *)
      v := vp↑.p↑.paramlist;
      vp := vp↑.dnext;		(* hack - up pointer to nesting proc defs *)
      bp := vp <> nil;
      end
     else
      begin			(* use block vars *)
      v := st↑.variables;
      st := st↑.bparent;
      end
   else	(* if dumb Pascal had short-circuit AND's this would be cleaner... *)
    begin			(* use block vars *)
    v := st↑.variables;
    st := st↑.bparent;
    end;
  while (v <> nil) and b do
   if v↑.name = id then b := false else v := v↑.next;
  end;
 if b then v := id↑.predefined;	(* maybe it's a predefined variable? *)
 varLookup := v;
 end;

(* aux routine: appendEnd *)

procedure appendEnd(s,so: statementp); external;
procedure appendEnd;
 var st: statementp;
 begin
 if so <> nil then
   begin
   st := newStatement;
   so↑.next := st;
   with st↑ do
    begin
    last := so;
    blkid := nil;
    stype := endtype;
    bparent := s;
    end;
   end;
 end;

(* aux routines for parsing expressions: defNode, getDtype, checkarg, copyExpr *)

 function defNode(d: datatypes): nodep; external;
 function defNode;
  var n: nodep;
  begin
  n := newNode;
  with n↑ do
   begin
   ntype := leafnode;
   ltype := d;
   case d of
svaltype: s := 0.0;
vectype:  v := nilvect;
rottype,
transtype: t := niltrans;
otherwise  {do nothing};
    end;
   end;
  defNode := n;
  end;

 function getDtype(n: nodep): datatypes; external;
 function getDtype;
  var da: datatypes;
  begin
  with n↑ do
   if ntype = leafnode then
     if ltype = varitype then da := vari↑.vtype
      else if ltype = pconstype then da := pcval↑.ltype
      else da := ltype
    else			(* see what type of op we've got *)
     if (svalop < op) and (op < vecop) or
	(ioop < op) and (op < specop) then da := svaltype else
     if (vecop < op) and (op < transop) then da := vectype else
     if (transop < op) and (op < ioop) then da := transtype else
     if (op = arefop) or (op = callop) then da := arg1↑.vari↑.vtype else
     if (op = grinchop) then da := getDtype(arg1) else
     if (op = vmop) or (op = adcop) then da := svaltype else
     if (op = badop) then da := getDtype(arg2) else da := nulltype;
  getDtype := da;
  end;

function checkArg(n: nodep; d: datatypes): nodep; external;
function checkArg;
 var bad: nodep; da: datatypes;
 begin
 if n = nil then checkArg := defNode(d)  (* use default value *)
  else
   begin
   da := getdtype(n);
   if (da <> d) and ((da = frametype) or (da = rottype)) then da := transtype;
   if (d = da) or ((d = rottype) and (da = transtype)) then
     checkArg := n			(* it's fine *)
    else if da = undeftype then
     begin				(* need to define the variable *)
     n↑.vari↑.vtype := d;
     checkArg := n;			(* but it's fine *)
     end
    else
     begin				(* no good - need to fix things up *)
     pp10L(' Found a  ',9); ppDtype(da);
     pp10(' where a  ',9); ppDtype(d);
     pp20(' should have been.  ',18);
     ppLine;
     bad := newNode;
     with bad↑ do
      begin
      ntype := exprnode;
      op := badop;
      arg1 := n;
      arg2 := defNode(d);
      arg3 := nil;
      end;
     checkArg := bad;
     end;
   end;
 end;

function copyExpr(n: nodep; lcp: boolean): nodep; external;
function copyExpr;
 var np: nodep;
 begin
 if n = nil then np := nil
  else
   with n↑ do
    begin
    if (ntype <> leafnode) or (ltype = varitype) or lcp then
      begin					(* need to make a copy *)
      np := newNode;
      np↑.ntype := ntype;
      case ntype of
arraydefnode:
       begin
       np↑.numdims := numdims;
       np↑.combnds := true;		(* indicate it's a copy *)
       np↑.bounds := copyexpr(bounds,false);
       end;
bnddefnode:
       begin
       np↑.next := copyexpr(next,false);
       np↑.lower := copyexpr(lower,false);
       np↑.upper := copyexpr(upper,false);
       end;
exprnode:
       begin
       np↑.op := op;
       if op = arefop then lcp := true;
       np↑.arg1 := copyexpr(arg1,false);
       np↑.arg2 := copyexpr(arg2,lcp);
       np↑.arg3 := copyexpr(arg3,false);
       end;
leafnode:
       begin
       np↑.ltype := ltype;
       np↑.length := length;		(* this should work for all leaftypes *)
       np↑.str := str
       end;
listnode:
       begin
       np↑.lval := copyexpr(lval,lcp);
       np↑.next := copyexpr(next,lcp);
       end;
otherwise {do nothing};
      end
     end
    else np := n;
   end;
 copyExpr := np;
 end;

(* basic read routine: readLine *)

procedure readline; external;
procedure readline;
 var i: integer;

procedure rdLine(var fi: atext);
 var ch: ascii; i,j: integer;

 procedure addit(c: c4str);
  var i: integer;
  begin
  if c[1] = ' ' then
    begin
    for i := 1 to 4 do line[maxchar+i] := c[i];
    ch := ' ';
    maxchar := maxchar + 4;
    end
   else
    begin
    line[maxchar] := c[1];
    ch := c[2];
    maxchar := maxchar + 1;
    end;
  end;

 begin
 maxchar := 0;
 if eofError or eof(fi) then
   begin
   if filedepth >= 1 then 
     begin			(* continue with last file *)
     filedepth := filedepth - 1;(* pop up a level *)
     ppLine;			(* give luser a sense of progress *)
     readline;			(* try again with popped file *)
     end
    else
     begin		     	(* yow - no file left - complain *)
     pp20L('*** End of File enco',20); pp20L('untered while parsin',20);
     pp10('g program ',10); ppLine;
     eofError := true;
     line[1] := 'E';		(* force parser to give up *)
     line[2] := 'N';
     line[3] := 'D';
     line[4] := ';';
     line[5] := ' ';
     curchar := 1;
     maxchar := 5;
     end
   end
  else
   begin			(* normal case - read in next line *)
   if eoln(fi) then readln(fi);
   while not eoln(fi) and (maxchar < 129) do
    begin
    maxchar := maxchar + 1;
    read(fi,line[maxchar]);
    if ord(line[maxchar]) = 11B then	(* turn tabs into spaces *)
      begin
      i := 8*(((maxchar - 1) div 8) + 1);
      for j := maxchar to i do line[j] := ' ';
      maxchar := i;
      end;
    end;
   line[maxchar+1] := ' ';	(* always can count on a final blank *)
   if line[1] <> chr(14B) then begin curchar := 1; curline := curline + 1; end
    else				(* new page *)
     begin
     curpage := curpage + 1;
     ppInt(curpage);		(* give luser a sense of progress *)
     ppChar(' ');
     ppOutNow;
     curline := 1;
     curchar := 2;
     line[1] := ' ';
     end;
   end;
 end;

 begin
  case filedepth of
0: begin
   maxChar := p1eReadLine(line);	
   curchar := 1; 
   end;
1: rdline(file1);
2: rdline(file2);
3: rdline(file3);
4: rdline(file4);
5: rdline(file5);
  end;
 shownline := false;
 end;